/** Fichier implémentant un cône.
 *
 * Ce fichier contient l'implémentation de la classe Cone.
 *
 * @file Cone.cpp
 * @author Johan "Solo" Luisier
 *
 * @date 4 Juillet 2011
 */
#include "Cone.hpp"

#include "Plan.hpp"
#include "BaseCone.hpp"

#include "Utils/ATL.hpp"

using namespace std;

/** Constructeur standard.
 *
 * Constructeur pertmettant d'initialiser tous les champs du Cone. La
 * transformation nécessaire pour passer en coordonnées locales est
 * initialisée ici. Comme pour Tore, on a un maximum de trois essais,
 * qui peut conduire à un arrêt du programme si tous échouent.
 *
 * Le Solveur utilisé pour la recherche d'intersection est initialisé
 * ici.
 *
 * @param[in] pt sommet du Cone.
 * @param[in] axe axe de symétrie du Cone.
 * @param[in] ouverture tangeante de l'angle d'ouverture.
 * @param[in] hauteur hauteur du Cone.
 */
Cone::Cone(const Coord& pt, const VecteurU& axe, const double& ouverture,
           const double& hauteur)
    : Hauteur( hauteur )
{
    form[ 0 ] = new Plan( axe, pt + hauteur * axe );
    form[ 1 ] = new BaseCone( pt, axe, ouverture );

    op = inter;

    PseudoRayon = hauteur * ( 1. + puissance< 2u >( ouverture ) ) / 2.;

    PseudoCentre = pt + PseudoRayon *  axe;
}

/** Destructeur, virtuel pour assurer une séquence de destruction correcte.
 *
 * Le destructeur doit libérer la mémoire allouée pour le solveur,
 */
Cone::~Cone()
{
    delete form[ 0 ];
    form[ 0 ] = 0;
    delete form[ 1 ];
    form[ 1 ] = 0;
}

/** Accesseur pour l'axe de l'instance de BaseCone.
 *
 * Appelle BaseCone::axe()
 *
 * @return une référence constante sur BaseCone::Axe.
 */
const VecteurU& Cone::axe() const
{
    return static_cast< const BaseCone* >( form[ 1 ] ) -> axe();
}

/** Accesseur pour le sommet de l'instance de BaseCone.
 *
 * Appelle BaseCone::sommet()
 *
 * @return une référence constante sur BaseCone::Sommet.
 */
const Coord& Cone::sommet() const
{
    return static_cast< const BaseCone* >( form[ 1 ] ) -> sommet();
}

/** Accesseur pour l'angle d'ouverture de l'instance de BaseCone.
 *
 * Appelle BaseCone::tanAlpha()
 *
 * @return une référence constante sur BaseCone::TanAlpha.
 */
const double& Cone::tanAlpha() const
{
    return static_cast< const BaseCone* >( form[ 1 ] ) -> tanAlpha();
}

/** Accesseur pour Hauteur.
 *
 * Permet d'accéder au membre Hauteur.
 *
 * @return une référence constante sur Hauteur.
 */
const double& Cone::hauteur() const
{
    return Hauteur;
}
